home *** CD-ROM | disk | FTP | other *** search
- /* This program simulates a constraint satisfaction
- neural network for choosing tic-tac-toe moves as
- described in Volume 2 of the PDP books. The
- network is presented a description of the board
- after each move and chooses the best move alternately
- for each side subject to predefined constraints.
-
- It requires an EGA or CGA to display a Hinton diagram
- of the element activation levels.
-
- Author : Gary Andriotakis
- Compiler : Microsoft Quick C
- Date : 5 January 1989
- */
- #include<stdio.h>
- #include <stdio.h>
- #include <time.h>
- #include <graph.h>
- #define N 67
- #define GAIN 0.1
- #define SCALE 1.0/16.0
- static float w[N][N], bias[N], a[N], e[2][N];
- main()
- {
- int i,j,n,mark = -1,converged;
- time_t t;
- if(!_setvideomode(_ERESCOLOR))
- { printf("EGA required\n");
- exit(0);
- }
- srand((int)time(&t));
- drawboard();
- n = 1;
- for(i = 0; i < 9; i++)
- { n = 1 - n;
- if(n)
- { _settextposition(2,2);
- _outtext("move x o empty 2x 2o 1x 1o");
- }
- else
- { _settextposition(2,2);
- _outtext("move o x empty 2o 2x 1o 1x");
- }
- putmarkers(&e[n][9],mark,1-n);
- initialize();
- boxes(a,N);
- do
- { j = randint(N);
- update(j,&e[n][0]);
- boxes(a,j);
- converged = ((j < 9) && (a[j] > 0.9));
- } while(!converged);
- mark = j;
- if(kbhit() && getch() == 27) break;
- }
- _setvideomode(_DEFAULTMODE);
- _displaycursor(_GCURSORON);
- }
-
- update(j,e)
- int j;
- float e[N];
- { int i;
- float net;
-
- net = 0.0;
- for(i = 0; i < N; i++)
- net += w[i][j]*a[i];
- net += bias[j];
- net *= GAIN;
- net += e[j];
- if(net > 0.0)
- a[j] += net*(1.0 - a[j]);
- else
- a[j] += net*a[j];
- }
-
- initialize()
- { int i,j;
- /* initialize to zero */
- for(i = 0; i < N; i++)
- { a[i] = 0.0;
- bias[i] = 0.0;
- for(j = 0; j < N; j++)
- w[i][j] = 0.0;
- }
-
- for(i = 0; i < 9; i++)
- { /* inhibit responses from occupied squares */
- w[i+9][i] = -8.0;
- w[i+18][i] = -8.0;
- /* mutual inhibition to insure only one response */
- for(j = 0; j < 9; j++)
- w[i][j] = -2.;
- w[i][i] = 2.;
- }
- /* empty line detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][27] = -1.0;
- w[i+18][27] = -1.0;
- w[27][i] = 1.0;
- w[i+12][28] = -1.0;
- w[i+21][28] = -1.0;
- w[28][i+3] = 1.0;
- w[i+15][29] = -1.0;
- w[i+24][29] = -1.0;
- w[29][i+6] = 1.0;
- w[9+4*i][30] = -1.0;
- w[18+4*i][30] = -1.0;
- w[30][4*i] = 1.0;
- w[11+2*i][31] = -1.0;
- w[20+2*i][31] = -1.0;
- w[31][2+2*i] = 1.0;
- w[9+3*i][32] = -1.0;
- w[18+3*i][32] = -1.0;
- w[32][3*i] = 1.0;
- w[10+3*i][33] = -1.0;
- w[19+3*i][33] = -1.0;
- w[33][1+3*i] = 1.0;
- w[11+3*i][34] = -1.0;
- w[20+3*i][34] = -1.0;
- w[34][2+3*i] = 1.0;
- }
- /* friendly doubleton detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][35] = 1.0;
- w[i+18][35] = -2.0;
- w[35][i] = 5.0;
- w[i+12][36] = 1.0;
- w[i+21][36] = -2.0;
- w[36][i+3] = 5.0;
- w[i+15][37] = 1.0;
- w[i+24][37] = -2.0;
- w[37][i+6] = 5.0;
- w[9+4*i][38] = 1.0;
- w[18+4*i][38] = -2.0;
- w[38][4*i] = 5.0;
- w[11+2*i][39] = 1.0;
- w[20+2*i][39] = -2.0;
- w[39][2+2*i] = 5.0;
- w[9+3*i][40] = 1.0;
- w[18+3*i][40] = -2.0;
- w[40][3*i] = 5.0;
- w[10+3*i][41] = 1.0;
- w[19+3*i][41] = -2.0;
- w[41][1+3*i] = 5.0;
- w[11+3*i][42] = 1.0;
- w[20+3*i][42] = -2.0;
- w[42][2+3*i] = 5.0;
- }
- /* enemy doubleton detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][43] = -2.0;
- w[i+18][43] = 1.0;
- w[43][i] = 1.0;
- w[i+12][44] = -2.0;
- w[i+21][44] = 1.0;
- w[44][i+3] = 1.0;
- w[i+15][45] = -2.0;
- w[i+24][45] = 1.0;
- w[45][i+6] = 1.0;
- w[9+4*i][46] = -2.0;
- w[18+4*i][46] = 1.0;
- w[46][4*i] = 1.0;
- w[11+2*i][47] = -2.0;
- w[20+2*i][47] = 1.0;
- w[47][2+2*i] = 1.0;
- w[9+3*i][48] = -2.0;
- w[18+3*i][48] = 1.0;
- w[48][3*i] = 1.0;
- w[10+3*i][49] = -2.0;
- w[19+3*i][49] = 1.0;
- w[49][1+3*i] = 1.0;
- w[11+3*i][50] = -2.0;
- w[20+3*i][50] = 1.0;
- w[50][2+3*i] = 1.0;
- }
- /* friendly singleton detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][51] = 1.0;
- w[i+18][51] = -2.0;
- w[51][i] = 2.0;
- w[i+12][52] = 1.0;
- w[i+21][52] = -2.0;
- w[52][i+3] = 2.0;
- w[i+15][53] = 1.0;
- w[i+24][53] = -2.0;
- w[53][i+6] = 2.0;
- w[9+4*i][54] = 1.0;
- w[18+4*i][54] = -2.0;
- w[54][4*i] = 2.0;
- w[11+2*i][55] = 1.0;
- w[20+2*i][55] = -2.0;
- w[55][2+2*i] = 2.0;
- w[9+3*i][56] = 1.0;
- w[18+3*i][56] = -2.0;
- w[56][3*i] = 2.0;
- w[10+3*i][57] = 1.0;
- w[19+3*i][57] = -2.0;
- w[57][1+3*i] = 2.0;
- w[11+3*i][58] = 1.0;
- w[20+3*i][58] = -2.0;
- w[58][2+3*i] = 2.0;
- }
- /* enemy singleton detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][59] = -2.0;
- w[i+18][59] = 1.0;
- w[59][i] = 2.0;
- w[i+12][60] = -2.0;
- w[i+21][60] = 1.0;
- w[60][i+3] = 2.0;
- w[i+15][61] = -2.0;
- w[i+24][61] = 1.0;
- w[61][i+6] = 2.0;
- w[9+4*i][62] = -2.0;
- w[18+4*i][62] = 1.0;
- w[62][4*i] = 2.0;
- w[11+2*i][63] = -2.0;
- w[20+2*i][63] = 1.0;
- w[63][2+2*i] = 2.0;
- w[9+3*i][64] = -2.0;
- w[18+3*i][64] = 1.0;
- w[64][3*i] = 2.0;
- w[10+3*i][65] = -2.0;
- w[19+3*i][65] = 1.0;
- w[65][1+3*i] = 2.0;
- w[11+3*i][66] = -2.0;
- w[20+3*i][66] = 1.0;
- w[66][2+3*i] = 2.0;
- }
- /* biases */
- for(i = 0; i < 9; i++)
- bias[i] = SCALE;
- for(i = 0; i < 8; i++)
- { bias[i+27] = 0.5;
- bias[i+35] = -1.5;
- bias[i+43] = -1.5;
- bias[i+51] = -0.5;
- bias[i+59] = -0.5;
- }
- for(i = 0; i < N; i++)
- { bias[i] *= SCALE;
- for(j = 0; j < N; j++)
- w[i][j] *= SCALE;
- }
- }
-
- randint(n)
- int n;
- {
- return(rand() % n);
- }
-
- #define MAXSIZE 5
- boxes(a,n)
- float a[];
- int n;
- {
- int i,j,k,x,y,x0,y0;
- int size,count;
-
- x0 = 5;
- y0 = 40;
- count = -1;
- for(k = 0; k < 3; k++)
- { x = x0;
- y = y0;
- for(i = 0; i < 3; i++)
- { for(j = 0; j < 3; j++)
- { x += 12;
- count++;
- if(n == N || n == count)
- { size = a[count]*MAXSIZE;
- _setcolor(0);
- _rectangle(_GFILLINTERIOR,
- x-MAXSIZE,y-MAXSIZE,x+MAXSIZE,y+MAXSIZE);
- _setcolor(15);
- _rectangle(_GBORDER,x-size,y-size,x+size,y+size);
- }
- }
- x = x0;
- y += 12;
- }
- x0 += 48;
- }
- y0 = 40;
- for(k = 0; k < 5; k++)
- { x = x0;
- y = y0;
- for(i = 0; i < 3; i++)
- { for(j = 0; j < 3; j++)
- { x += 12;
- if(i != 1 || j != 1)
- { count++;
- if(n == N || n == count)
- { size = a[count]*MAXSIZE;
- _setcolor(0);
- _rectangle(_GFILLINTERIOR,
- x-MAXSIZE,y-MAXSIZE,x+MAXSIZE,y+MAXSIZE);
- _setcolor(15);
- _rectangle(_GBORDER,x-size,y-size,x+size,y+size);
- }
- }
- }
- x = x0;
- y += 12;
- }
- x0 += 48;
- }
- }
-
- drawboard()
- { static char board[5][6] = {32,179,32,179,32,0,
- 196,197,196,197,196,0,
- 32,179,32,179,32,0,
- 196,197,196,197,196,0,
- 32,179,32,179,32,0};
- int i;
- _clearscreen(_GCLEARSCREEN);
- for(i = 0; i < 5; i++)
- { _settextposition(i+8,37);
- _outtext(&board[i][0]);
- }
- _settextposition(19,5);
- _outtext("This is a tic-tac-toe game where a neural network plays");
- _settextposition(20,5);
- _outtext("both sides of the game. Alternating representations of the");
- _settextposition(21,5);
- _outtext("board are presented to the same network. Hitting");
- _settextposition(22,5);
- _outtext("ESCAPE while the network is running will exit program");
- _settextposition(23,5);
- _outtext("when the current move is complete.");
- }
-
- putmarkers(b,x,n)
- float b[];
- int x; /* location of programs new move */
- /*
- * puts x's and o's on the board
- * x is the programs marker,
- * o is the opponents marker
- */
- { int i,row,col;
- static int board[9] = {0};
- int c, c1;
-
- if(x > -1)
- { _settextposition(8+2*(x/3),37+2*(x%3));
- if(n == 0)
- _outtext("x");
- else
- _outtext("o");
- board[x] = n+1;
- }
- for(i = 0; i < 9; i++)
- { if(board[i] == 0)
- { b[i] = 0.0;
- b[i+9] = 0.0;
- }
- else if(((board[i] == 1) && (n == 0)) ||
- ((board[i] == 2) && (n == 1)))
- { b[i] = 1.0;
- b[i+9] = 0.0;
- }
- else if(((board[i] == 2) && (n == 0)) ||
- ((board[i] == 1) && (n == 1)))
- { b[i] = 0.0;
- b[i+9] = 1.0;
- }
- }
- }
-
- == 0)) ||
- ((board[i] == 1) && (n == 1)))
- { b[i] = 0.0;
- b[i+9] = 1.0;
- }
- }
- w[49][1+3*i] = 1.0;
- w[11+3*i][50] = -2.0;
- w[20+3*i][50] = 1.0;
- w[50][2+3*i] = 1.0;
- }
- /* friendly singleton detectors */
- for(i = 0; i < 3; i++)
- { w[i+9][51] = 1.0;
- w[i+18][51] = -2.0;
- w[51][i] = 2.0;
- w[i+12][52] = 1.0;
- w[i+21][52] = -2.0;
- w[52][i+3] = 2.0;
- w[i+15][53] = 1.0;
- w[i+24][53] = -2.0;
- w[53][i+6] = 2.0;
- w[9+4*i][54] = 1.0;
- w[18+4*i][54] = -2.0;
- w[54][4*i] = 2.0;
- w[11+2*i][55] = 1.0;
- w[20+2*i][55] = -2.0;
- w[55][2+2*i] = 2.0;
- w[9+3*i][56] = 1.0;
- w[18+3*i][56] = -2.0;
- w[56][3*i] = 2.0;
- w[10+3*i][57] = 1.0;
- w[19+3*i][57] = -2.0;
- w[57][1+3*i] = 2.0;
- w[11+3*i][58] = 1.0